import React from 'react'
import { Col, Form, Row } from 'antd'

import { EditFormProps } from './interface'

const EditableFormComp = ({ editable = true, formProps, formSchema, form: formInstance, span = 12 }: EditFormProps) => {
  const [innerForm] = Form.useForm()
  const form = formInstance ?? innerForm

  return (
    <Form {...formProps} form={form}>
      <Row gutter={16}>
        {formSchema.map(item => {
          const deps = item.dependencies
          return (
            <Form.Item
              // 使用 shouldUpdate 保证在依赖字段变化时，当前项的 hidden/props 重新计算
              noStyle
              dependencies={deps}
              shouldUpdate={(prev, cur) => {
                if (!deps || deps.length === 0) return true
                return deps.some(d => prev?.[d] !== cur?.[d])
              }}
              key={`wrapper-${item.name}`}
            >
              {(formInst: any) => {
                const record = formInst.getFieldsValue(true)
                const canEditItem =
                  editable &&
                  (typeof item.editable === 'function' ? item.editable({ record }) : (item.editable ?? true))
                const hidden = item.hidden ?? false
                const isHidden = typeof hidden === 'function' ? hidden({ record }) : hidden

                const formItemProps =
                  typeof item.formItemProps === 'function' ? item.formItemProps({ record }) : item.formItemProps || {}
                const componentProps =
                  typeof item.componentProps === 'function'
                    ? item.componentProps({ record })
                    : item.componentProps || {}
                const label = typeof item.label === 'function' ? item.label({ record, name: item.name }) : item.label
                const spanNumber = typeof item.span === 'function' ? item.span({ record, name: item.name }) : span
                return isHidden ? (
                  <Form.Item name={item.name} noStyle />
                ) : (
                  <Col span={spanNumber || span} key={item.name}>
                    <Form.Item name={item.name} label={label} colon={false} {...formItemProps}>
                      {canEditItem
                        ? React.isValidElement(item.component)
                          ? React.cloneElement(item.component, { ...componentProps, record })
                          : (() => {
                              const Comp = item.component as React.ComponentType<any>
                              return <Comp {...componentProps} record={record} />
                            })()
                        : item.renderView
                          ? item.renderView({ record, name: item.name })
                          : (() => {
                              const v = record?.[item.name]
                              if (v == null) return '-'
                              if (React.isValidElement(v)) return v
                              if (typeof v === 'object') {
                                const maybeRange = v as any
                                if ('minVal' in maybeRange || 'maxVal' in maybeRange) {
                                  const min = maybeRange.minVal ?? '-'
                                  const max = maybeRange.maxVal ?? '-'
                                  return `${min} ~ ${max}`
                                }
                                return '-'
                              }
                              return String(v)
                            })()}
                    </Form.Item>
                  </Col>
                )
              }}
            </Form.Item>
          )
        })}
      </Row>
    </Form>
  )
}

type EditableFormType = typeof EditableFormComp & { useForm: typeof Form.useForm }
export const EditableForm = EditableFormComp as EditableFormType
EditableForm.useForm = Form.useForm

export default EditableForm
